/**
 * thrift客户端
 *
 * Created by snowingsea on 2020/03/01.
 */

const thrift = require('thrift');
const debug = require('debug')('phoenix:hydra');
const logger = require('../logger');
const rocketService = require('./../../../lib/server/dist/thrift/gen-nodejs/Service');
const rocketTypes = require('./../../../lib/server/dist/thrift/gen-nodejs/rocket_types');

let connection = null;
let thriftClient = null;

/**
 * 断开连接
 * @return {Promise}
 */
function disconnect() {
  // if (connection) {
  //   connection.end();
  // }
  connection = null;
  return Promise.resolve();
}

/**
 * 连接
 * @return {Promise}
 */
function connect() {
  return new Promise((resolve, reject) => {
    disconnect()
      .then(() => {
        const { host, port } = global.config.hydra;
        connection = thrift.createHttpConnection(host, port, {
          transport: thrift.TBufferedTransport,
          protocol: thrift.TBinaryProtocol,
        });
        connection.on('error', (err) => {
          logger.error(`Fail to connect Hydra: ${err}`);
          debug('The connection will be tried again in 10 seconds...');
          setTimeout(() => {
            connect().then(resolve).catch(reject);
          }, 10000);
        });
        // eslint-disable-next-line no-use-before-define
        createClient()
          .then((client) => {
            client.compilation_options_query((err, data) => {
              if (!err) {
                debug(`Successfully Connect to Hydra(${host}:${port})`);
                resolve(data);
                return;
              }
              logger.error(`Fail to connect Hydra: ${err}`);
              debug('The connection will be tried again in 10 seconds...');
              setTimeout(() => {
                connect().then(resolve).catch(reject);
              }, 10000);
            });
          });
      })
      .catch(reject);
  });
}

/**
 * 创建客户端
 * @return {Promise}
 */
function createClient() {
  return new Promise((resolve, reject) => {
    Promise.resolve()
      .then(() => {
        if (connection) {
          return Promise.resolve();
        }
        return connect();
      })
      .then(() => {
        if (!thriftClient) {
          thriftClient = thrift.createClient(rocketService, connection);
        }
        resolve(thriftClient);
      })
      .catch(reject);
  });
}

/**
 * Export model definition object.
 */
module.exports = {
  types: rocketTypes,

  connect,
  disconnect,
  createClient,
};
